home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / base / ftstream.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  17.7 KB  |  805 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftstream.c                                                             */
  4. /*                                                                         */
  5. /*    I/O stream support (body).                                           */
  6. /*                                                                         */
  7. /*  Copyright 2000-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_INTERNAL_DEBUG_H
  22.  
  23.  
  24.   /*************************************************************************/
  25.   /*                                                                       */
  26.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  27.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  28.   /* messages during execution.                                            */
  29.   /*                                                                       */
  30. #undef  FT_COMPONENT
  31. #define FT_COMPONENT  trace_stream
  32.  
  33.  
  34.   FT_BASE_DEF( void )
  35.   FT_New_Memory_Stream( FT_Library  library,
  36.                         FT_Byte*    base,
  37.                         FT_ULong    size,
  38.                         FT_Stream   stream )
  39.   {
  40.     stream->memory = library->memory;
  41.     stream->base   = base;
  42.     stream->size   = size;
  43.     stream->pos    = 0;
  44.     stream->cursor = 0;
  45.     stream->read   = 0;
  46.     stream->close  = 0;
  47.   }
  48.  
  49.  
  50.   FT_BASE_DEF( FT_Error )
  51.   FT_Seek_Stream( FT_Stream  stream,
  52.                   FT_ULong   pos )
  53.   {
  54.     FT_Error  error;
  55.  
  56.  
  57.     stream->pos = pos;
  58.  
  59.     if ( stream->read )
  60.     {
  61.       if ( stream->read( stream, pos, 0, 0 ) )
  62.       {
  63.         FT_ERROR(( "FT_Seek_Stream:" ));
  64.         FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  65.                    pos, stream->size ));
  66.  
  67.         error = FT_Err_Invalid_Stream_Operation;
  68.       }
  69.       else
  70.         error = FT_Err_Ok;
  71.     }
  72.     /* note that seeking to the first position after the file is valid */
  73.     else if ( pos > stream->size )
  74.     {
  75.       FT_ERROR(( "FT_Seek_Stream:" ));
  76.       FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  77.                  pos, stream->size ));
  78.  
  79.       error = FT_Err_Invalid_Stream_Operation;
  80.     }
  81.  
  82.     else
  83.       error = FT_Err_Ok;
  84.  
  85.     return error;
  86.   }
  87.  
  88.  
  89.   FT_BASE_DEF( FT_Error )
  90.   FT_Skip_Stream( FT_Stream  stream,
  91.                   FT_Long    distance )
  92.   {
  93.     return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
  94.   }
  95.  
  96.  
  97.   FT_BASE_DEF( FT_Long )
  98.   FT_Stream_Pos( FT_Stream  stream )
  99.   {
  100.     return stream->pos;
  101.   }
  102.  
  103.  
  104.   FT_BASE_DEF( FT_Error )
  105.   FT_Read_Stream( FT_Stream  stream,
  106.                   FT_Byte*   buffer,
  107.                   FT_ULong   count )
  108.   {
  109.     return FT_Read_Stream_At( stream, stream->pos, buffer, count );
  110.   }
  111.  
  112.  
  113.   FT_BASE_DEF( FT_Error )
  114.   FT_Read_Stream_At( FT_Stream  stream,
  115.                      FT_ULong   pos,
  116.                      FT_Byte*   buffer,
  117.                      FT_ULong   count )
  118.   {
  119.     FT_Error  error = FT_Err_Ok;
  120.     FT_ULong  read_bytes;
  121.  
  122.  
  123.     if ( pos >= stream->size )
  124.     {
  125.       FT_ERROR(( "FT_Read_Stream_At:" ));
  126.       FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  127.                  pos, stream->size ));
  128.  
  129.       return FT_Err_Invalid_Stream_Operation;
  130.     }
  131.  
  132.     if ( stream->read )
  133.       read_bytes = stream->read( stream, pos, buffer, count );
  134.     else
  135.     {
  136.       read_bytes = stream->size - pos;
  137.       if ( read_bytes > count )
  138.         read_bytes = count;
  139.  
  140.       MEM_Copy( buffer, stream->base + pos, read_bytes );
  141.     }
  142.  
  143.     stream->pos = pos + read_bytes;
  144.  
  145.     if ( read_bytes < count )
  146.     {
  147.       FT_ERROR(( "FT_Read_Stream_At:" ));
  148.       FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
  149.                  count, read_bytes ));
  150.  
  151.       error = FT_Err_Invalid_Stream_Operation;
  152.     }
  153.  
  154.     return error;
  155.   }
  156.  
  157.  
  158.   FT_BASE_DEF( FT_Error )
  159.   FT_Extract_Frame( FT_Stream  stream,
  160.                     FT_ULong   count,
  161.                     FT_Byte**  pbytes )
  162.   {
  163.     FT_Error  error;
  164.  
  165.  
  166.     error = FT_Access_Frame( stream, count );
  167.     if ( !error )
  168.     {
  169.       *pbytes = (FT_Byte*)stream->cursor;
  170.  
  171.       /* equivalent to FT_Forget_Frame(), with no memory block release */
  172.       stream->cursor = 0;
  173.       stream->limit  = 0;
  174.     }
  175.  
  176.     return error;
  177.   }
  178.  
  179.  
  180.   FT_BASE_DEF( void )
  181.   FT_Release_Frame( FT_Stream  stream,
  182.                     FT_Byte**  pbytes )
  183.   {
  184.     if ( stream->read )
  185.     {
  186.       FT_Memory  memory = stream->memory;
  187.  
  188.  
  189.       FREE( *pbytes );
  190.     }
  191.     *pbytes = 0;
  192.   }
  193.  
  194.  
  195.   FT_BASE_DEF( FT_Error )
  196.   FT_Access_Frame( FT_Stream  stream,
  197.                    FT_ULong   count )
  198.   {
  199.     FT_Error  error = FT_Err_Ok;
  200.     FT_ULong  read_bytes;
  201.  
  202.  
  203.     /* check for nested frame access */
  204.     FT_Assert( stream && stream->cursor == 0 );
  205.  
  206.     if ( stream->read )
  207.     {
  208.       /* allocate the frame in memory */
  209.       FT_Memory  memory = stream->memory;
  210.  
  211.  
  212.       if ( ALLOC( stream->base, count ) )
  213.         goto Exit;
  214.  
  215.       /* read it */
  216.       read_bytes = stream->read( stream, stream->pos,
  217.                                  stream->base, count );
  218.       if ( read_bytes < count )
  219.       {
  220.         FT_ERROR(( "FT_Access_Frame:" ));
  221.         FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
  222.                    count, read_bytes ));
  223.  
  224.         FREE( stream->base );
  225.         error = FT_Err_Invalid_Stream_Operation;
  226.       }
  227.       stream->cursor = stream->base;
  228.       stream->limit  = stream->cursor + count;
  229.       stream->pos   += read_bytes;
  230.     }
  231.     else
  232.     {
  233.       /* check current and new position */
  234.       if ( stream->pos >= stream->size        ||
  235.            stream->pos + count > stream->size )
  236.       {
  237.         FT_ERROR(( "FT_Access_Frame:" ));
  238.         FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
  239.                    stream->pos, count, stream->size ));
  240.  
  241.         error = FT_Err_Invalid_Stream_Operation;
  242.         goto Exit;
  243.       }
  244.  
  245.       /* set cursor */
  246.       stream->cursor = stream->base + stream->pos;
  247.       stream->limit  = stream->cursor + count;
  248.       stream->pos   += count;
  249.     }
  250.  
  251.   Exit:
  252.     return error;
  253.   }
  254.  
  255.  
  256.   FT_BASE_DEF( void )
  257.   FT_Forget_Frame( FT_Stream  stream )
  258.   {
  259.     /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
  260.     /*            that it is possible to access a frame of length 0 in    */
  261.     /*            some weird fonts (usually, when accessing an array of   */
  262.     /*            0 records, like in some strange kern tables).           */
  263.     /*                                                                    */
  264.     /*  In this case, the loader code handles the 0-length table          */
  265.     /*  gracefully; however, stream.cursor is really set to 0 by the      */
  266.     /*  FT_Access_Frame() call, and this is not an error.                 */
  267.     /*                                                                    */
  268.     FT_Assert( stream );
  269.  
  270.     if ( stream->read )
  271.     {
  272.       FT_Memory  memory = stream->memory;
  273.  
  274.  
  275.       FREE( stream->base );
  276.     }
  277.     stream->cursor = 0;
  278.     stream->limit  = 0;
  279.   }
  280.  
  281.  
  282.   FT_BASE_DEF( FT_Char )
  283.   FT_Get_Char( FT_Stream  stream )
  284.   {
  285.     FT_Char  result;
  286.  
  287.  
  288.     FT_Assert( stream && stream->cursor );
  289.  
  290.     result = 0;
  291.     if ( stream->cursor < stream->limit )
  292.       result = *stream->cursor++;
  293.  
  294.     return result;
  295.   }
  296.  
  297.  
  298.   FT_BASE_DEF( FT_Short )
  299.   FT_Get_Short( FT_Stream  stream )
  300.   {
  301.     FT_Byte*  p;
  302.     FT_Short  result;
  303.  
  304.  
  305.     FT_Assert( stream && stream->cursor );
  306.  
  307.     result         = 0;
  308.     p              = stream->cursor;
  309.     if ( p + 1 < stream->limit )
  310.       result       = NEXT_Short( p );
  311.     stream->cursor = p;
  312.  
  313.     return result;
  314.   }
  315.  
  316.  
  317.   FT_BASE_DEF( FT_Short )
  318.   FT_Get_ShortLE( FT_Stream  stream )
  319.   {
  320.     FT_Byte*  p;
  321.     FT_Short  result;
  322.  
  323.  
  324.     FT_Assert( stream && stream->cursor );
  325.  
  326.     result         = 0;
  327.     p              = stream->cursor;
  328.     if ( p + 1 < stream->limit )
  329.       result       = NEXT_ShortLE( p );
  330.     stream->cursor = p;
  331.  
  332.     return result;
  333.   }
  334.  
  335.  
  336.   FT_BASE_DEF( FT_Long )
  337.   FT_Get_Offset( FT_Stream  stream )
  338.   {
  339.     FT_Byte*  p;
  340.     FT_Long   result;
  341.  
  342.  
  343.     FT_Assert( stream && stream->cursor );
  344.  
  345.     result         = 0;
  346.     p              = stream->cursor;
  347.     if ( p + 2 < stream->limit )
  348.       result       = NEXT_Offset( p );
  349.     stream->cursor = p;
  350.     return result;
  351.   }
  352.  
  353.  
  354.   FT_BASE_DEF( FT_Long )
  355.   FT_Get_Long( FT_Stream  stream )
  356.   {
  357.     FT_Byte*  p;
  358.     FT_Long   result;
  359.  
  360.  
  361.     FT_Assert( stream && stream->cursor );
  362.  
  363.     result         = 0;
  364.     p              = stream->cursor;
  365.     if ( p + 3 < stream->limit )
  366.       result       = NEXT_Long( p );
  367.     stream->cursor = p;
  368.     return result;
  369.   }
  370.  
  371.  
  372.   FT_BASE_DEF( FT_Long )
  373.   FT_Get_LongLE( FT_Stream  stream )
  374.   {
  375.     FT_Byte*  p;
  376.     FT_Long   result;
  377.  
  378.  
  379.     FT_Assert( stream && stream->cursor );
  380.  
  381.     result         = 0;
  382.     p              = stream->cursor;
  383.     if ( p + 3 < stream->limit )
  384.       result       = NEXT_LongLE( p );
  385.     stream->cursor = p;
  386.     return result;
  387.   }
  388.  
  389.  
  390.   FT_BASE_DEF( FT_Char )
  391.   FT_Read_Char( FT_Stream  stream,
  392.                 FT_Error*  error )
  393.   {
  394.     FT_Byte  result = 0;
  395.  
  396.  
  397.     FT_Assert( stream );
  398.  
  399.     *error = FT_Err_Ok;
  400.  
  401.     if ( stream->read )
  402.     {
  403.       if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
  404.         goto Fail;
  405.     }
  406.     else
  407.     {
  408.       if ( stream->pos < stream->size )
  409.         result = stream->base[stream->pos];
  410.       else
  411.         goto Fail;
  412.     }
  413.     stream->pos++;
  414.  
  415.     return result;
  416.  
  417.   Fail:
  418.     *error = FT_Err_Invalid_Stream_Operation;
  419.     FT_ERROR(( "FT_Read_Char:" ));
  420.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  421.                stream->pos, stream->size ));
  422.  
  423.     return 0;
  424.   }
  425.  
  426.  
  427.   FT_BASE_DEF( FT_Short )
  428.   FT_Read_Short( FT_Stream  stream,
  429.                  FT_Error*  error )
  430.   {
  431.     FT_Byte   reads[2];
  432.     FT_Byte*  p = 0;
  433.     FT_Short  result = 0;
  434.  
  435.  
  436.     FT_Assert( stream );
  437.  
  438.     *error = FT_Err_Ok;
  439.  
  440.     if ( stream->pos + 1 < stream->size )
  441.     {
  442.       if ( stream->read )
  443.       {
  444.         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
  445.           goto Fail;
  446.  
  447.         p = reads;
  448.       }
  449.       else
  450.       {
  451.         p = stream->base + stream->pos;
  452.       }
  453.  
  454.       if ( p )
  455.         result = NEXT_Short( p );
  456.     }
  457.     else
  458.       goto Fail;
  459.  
  460.     stream->pos += 2;
  461.  
  462.     return result;
  463.  
  464.   Fail:
  465.     *error = FT_Err_Invalid_Stream_Operation;
  466.     FT_ERROR(( "FT_Read_Short:" ));
  467.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  468.                stream->pos, stream->size ));
  469.  
  470.     return 0;
  471.   }
  472.  
  473.  
  474.   FT_BASE_DEF( FT_Short )
  475.   FT_Read_ShortLE( FT_Stream  stream,
  476.                    FT_Error*  error )
  477.   {
  478.     FT_Byte   reads[2];
  479.     FT_Byte*  p = 0;
  480.     FT_Short  result = 0;
  481.  
  482.  
  483.     FT_Assert( stream );
  484.  
  485.     *error = FT_Err_Ok;
  486.  
  487.     if ( stream->pos + 1 < stream->size )
  488.     {
  489.       if ( stream->read )
  490.       {
  491.         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
  492.           goto Fail;
  493.  
  494.         p = reads;
  495.       }
  496.       else
  497.       {
  498.         p = stream->base + stream->pos;
  499.       }
  500.  
  501.       if ( p )
  502.         result = NEXT_ShortLE( p );
  503.     }
  504.     else
  505.       goto Fail;
  506.  
  507.     stream->pos += 2;
  508.  
  509.     return result;
  510.  
  511.   Fail:
  512.     *error = FT_Err_Invalid_Stream_Operation;
  513.     FT_ERROR(( "FT_Read_Short:" ));
  514.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  515.                stream->pos, stream->size ));
  516.  
  517.     return 0;
  518.   }
  519.  
  520.  
  521.   FT_BASE_DEF( FT_Long )
  522.   FT_Read_Offset( FT_Stream  stream,
  523.                   FT_Error*  error )
  524.   {
  525.     FT_Byte   reads[3];
  526.     FT_Byte*  p = 0;
  527.     FT_Long   result = 0;
  528.  
  529.  
  530.     FT_Assert( stream );
  531.  
  532.     *error = FT_Err_Ok;
  533.  
  534.     if ( stream->pos + 2 < stream->size )
  535.     {
  536.       if ( stream->read )
  537.       {
  538.         if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
  539.           goto Fail;
  540.  
  541.         p = reads;
  542.       }
  543.       else
  544.       {
  545.         p = stream->base + stream->pos;
  546.       }
  547.  
  548.       if ( p )
  549.         result = NEXT_Offset( p );
  550.     }
  551.     else
  552.       goto Fail;
  553.  
  554.     stream->pos += 3;
  555.  
  556.     return result;
  557.  
  558.   Fail:
  559.     *error = FT_Err_Invalid_Stream_Operation;
  560.     FT_ERROR(( "FT_Read_Offset:" ));
  561.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  562.                stream->pos, stream->size ));
  563.  
  564.     return 0;
  565.   }
  566.  
  567.  
  568.   FT_BASE_DEF( FT_Long )
  569.   FT_Read_Long( FT_Stream  stream,
  570.                 FT_Error*  error )
  571.   {
  572.     FT_Byte   reads[4];
  573.     FT_Byte*  p = 0;
  574.     FT_Long   result = 0;
  575.  
  576.  
  577.     FT_Assert( stream );
  578.  
  579.     *error = FT_Err_Ok;
  580.  
  581.     if ( stream->pos + 3 < stream->size )
  582.     {
  583.       if ( stream->read )
  584.       {
  585.         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
  586.           goto Fail;
  587.  
  588.         p = reads;
  589.       }
  590.       else
  591.       {
  592.         p = stream->base + stream->pos;
  593.       }
  594.  
  595.       if ( p )
  596.         result = NEXT_Long( p );
  597.     }
  598.     else
  599.       goto Fail;
  600.  
  601.     stream->pos += 4;
  602.  
  603.     return result;
  604.  
  605.   Fail:
  606.     FT_ERROR(( "FT_Read_Long:" ));
  607.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  608.                stream->pos, stream->size ));
  609.     *error = FT_Err_Invalid_Stream_Operation;
  610.  
  611.     return 0;
  612.   }
  613.  
  614.  
  615.   FT_BASE_DEF( FT_Long )
  616.   FT_Read_LongLE( FT_Stream  stream,
  617.                   FT_Error*  error )
  618.   {
  619.     FT_Byte   reads[4];
  620.     FT_Byte*  p = 0;
  621.     FT_Long   result = 0;
  622.  
  623.  
  624.     FT_Assert( stream );
  625.  
  626.     *error = FT_Err_Ok;
  627.  
  628.     if ( stream->pos + 3 < stream->size )
  629.     {
  630.       if ( stream->read )
  631.       {
  632.         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
  633.           goto Fail;
  634.  
  635.         p = reads;
  636.       }
  637.       else
  638.       {
  639.         p = stream->base + stream->pos;
  640.       }
  641.  
  642.       if ( p )
  643.         result = NEXT_LongLE( p );
  644.     }
  645.     else
  646.       goto Fail;
  647.  
  648.     stream->pos += 4;
  649.  
  650.     return result;
  651.  
  652.   Fail:
  653.     FT_ERROR(( "FT_Read_Long:" ));
  654.     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  655.                stream->pos, stream->size ));
  656.     *error = FT_Err_Invalid_Stream_Operation;
  657.  
  658.     return 0;
  659.   }
  660.  
  661.  
  662.   FT_BASE_DEF( FT_Error )
  663.   FT_Read_Fields( FT_Stream              stream,
  664.                   const FT_Frame_Field*  fields,
  665.                   void*                  structure )
  666.   {
  667.     FT_Error  error;
  668.     FT_Bool   frame_accessed = 0;
  669.     FT_Byte*  cursor = stream->cursor;
  670.  
  671.  
  672.     if ( !fields || !stream )
  673.       return FT_Err_Invalid_Argument;
  674.  
  675.     error = FT_Err_Ok;
  676.     do
  677.     {
  678.       FT_ULong  value;
  679.       FT_Int    sign_shift;
  680.       FT_Byte*  p;
  681.  
  682.  
  683.       switch ( fields->value )
  684.       {
  685.       case ft_frame_start:  /* access a new frame */
  686.         error = FT_Access_Frame( stream, fields->offset );
  687.         if ( error )
  688.           goto Exit;
  689.  
  690.         frame_accessed = 1;
  691.         cursor         = stream->cursor;
  692.         fields++;
  693.         continue;  /* loop! */
  694.  
  695.       case ft_frame_bytes:  /* read a byte sequence */
  696.       case ft_frame_skip:   /* skip some bytes      */
  697.         {
  698.           FT_UInt  len = fields->size;
  699.  
  700.  
  701.           if ( cursor + len > stream->limit )
  702.           {
  703.             error = FT_Err_Invalid_Stream_Operation;
  704.             goto Exit;
  705.           }
  706.  
  707.           if ( fields->value == ft_frame_bytes )
  708.           {
  709.             p = (FT_Byte*)structure + fields->offset;
  710.             MEM_Copy( p, cursor, len );
  711.           }
  712.           cursor += len;
  713.           fields++;
  714.           continue;
  715.         }
  716.  
  717.       case ft_frame_byte:
  718.       case ft_frame_schar:  /* read a single byte */
  719.         value = NEXT_Byte(cursor);
  720.         sign_shift = 24;
  721.         break;
  722.  
  723.       case ft_frame_short_be:
  724.       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
  725.         value = NEXT_UShort(cursor);
  726.         sign_shift = 16;
  727.         break;
  728.  
  729.       case ft_frame_short_le:
  730.       case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
  731.         value = NEXT_UShortLE(cursor);
  732.         sign_shift = 16;
  733.         break;
  734.  
  735.       case ft_frame_long_be:
  736.       case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
  737.         value = NEXT_ULong(cursor);
  738.         sign_shift = 0;
  739.         break;
  740.  
  741.       case ft_frame_long_le:
  742.       case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
  743.         value = NEXT_ULongLE(cursor);
  744.         sign_shift = 0;
  745.         break;
  746.  
  747.       case ft_frame_off3_be:
  748.       case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
  749.         value = NEXT_UOffset(cursor);
  750.         sign_shift = 8;
  751.         break;
  752.  
  753.       case ft_frame_off3_le:
  754.       case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
  755.         value = NEXT_UOffsetLE(cursor);
  756.         sign_shift = 8;
  757.         break;
  758.  
  759.       default:
  760.         /* otherwise, exit the loop */
  761.         stream->cursor = cursor;
  762.         goto Exit;
  763.       }
  764.  
  765.       /* now, compute the signed value is necessary */
  766.       if ( fields->value & FT_FRAME_OP_SIGNED )
  767.         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
  768.  
  769.       /* finally, store the value in the object */
  770.  
  771.       p = (FT_Byte*)structure + fields->offset;
  772.       switch ( fields->size )
  773.       {
  774.       case 1:
  775.         *(FT_Byte*)p = (FT_Byte)value;
  776.         break;
  777.  
  778.       case 2:
  779.         *(FT_UShort*)p = (FT_UShort)value;
  780.         break;
  781.  
  782.       case 4:
  783.         *(FT_UInt32*)p = (FT_UInt32)value;
  784.         break;
  785.  
  786.       default:  /* for 64-bit systems */
  787.         *(FT_ULong*)p = (FT_ULong)value;
  788.       }
  789.  
  790.       /* go to next field */
  791.       fields++;
  792.     }
  793.     while ( 1 );
  794.  
  795.   Exit:
  796.     /* close the frame if it was opened by this read */
  797.     if ( frame_accessed )
  798.       FT_Forget_Frame( stream );
  799.  
  800.     return error;
  801.   }
  802.  
  803.  
  804. /* END */
  805.